package com.tuzhi.filestore.websocket.server;

import cn.hutool.core.collection.ConcurrentHashSet;
import com.alibaba.fastjson.JSONObject;
import com.tuzhi.common.exception.BusinessException;
import com.tuzhi.filestore.model.response.Result;
import com.tuzhi.filestore.model.response.Results;
import com.tuzhi.filestore.vo.MsgVo;
import com.tuzhi.filestore.websocket.enums.MsgTypeEnum;
import com.tuzhi.filestore.websocket.vo.MessageVo;
import com.tuzhi.filestore.websocket.vo.OrderStatusMsgVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 功能说明：
 *
 * @author abu
 * @version 1.1.0
 * @date 2023/2/21
 */

public class WebSocketHelp {

    static Logger log = LoggerFactory.getLogger(WebSocketHelp.class.getName());

    /**
     * 获取当前用户的实例
     *
     * @param userId
     * @return
     */
    private static FileStoreWebSocketServer getWs4UserId(String userId) {
        if (StringUtils.isEmpty(userId)) {
            throw new BusinessException("userid 不能为空");
        }
        ConcurrentHashMap<String, FileStoreWebSocketServer> userMap = FileStoreWebSocketServer.getWebSocketMap();
        if (userMap == null) {
            throw new BusinessException("实例池为空");
        }

        FileStoreWebSocketServer curWs = userMap.get(userId);
        if (curWs == null) {
            throw new BusinessException("找不到对应的用户的实例，没连接或己断开");
        }
        return curWs;
    }


    /**
     * 发送消息
     *
     * @param userId 用户ID
     * @param msg    消息体
     * @return
     */
    public static Result sendMsg(String userId, String msg) {
        Result ret = null;
        try {
            getWs4UserId(userId).sendMessage(msg);
            ret = Results.newSuccessResult(msg, "发送消息成功->" + userId);
            return ret;
        } catch (Exception ex) {
            log.warn("发送消息异常：" + ex.getMessage());
            ret = Results.newSuccessResult(msg, "发送消息失败->" + userId + ex.getMessage());
            return ret;
        }
    }


    /**
     * 发送到客户端的消息通知
     *
     * @param userId
     * @param msg
     * @return
     */
    public static Result sendClientMsg(String userId, Map<String, Object> msg) {
        Result ret = null;
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.fluentPutAll(msg);
            sendMsg(userId, jsonObject.toJSONString());
            ret = Results.newSuccessResult(msg, "发送消息成功->" + userId);
            return ret;
        } catch (Exception ex) {
            log.warn("发送消息异常：" + ex.getMessage());
            ret = Results.newSuccessResult(msg, "发送消息失败->" + userId + ex.getMessage());
            return ret;
        }

    }

    /**
     * 发送到客户端的消息通知
     *
     * @param userId
     * @param msg
     * @return
     */
    public static Result sendClientMsg1(String userId, MsgVo msg) {
        Result ret = null;
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type", msg.getType());
            jsonObject.put("msg", msg.getMsg());
            sendMsg(userId, jsonObject.toJSONString());
            ret = Results.newSuccessResult(msg, "发送消息成功->" + userId);
            return ret;
        } catch (Exception ex) {
            log.warn("发送消息异常：" + ex.getMessage());
            ret = Results.newSuccessResult(msg, "发送消息失败->" + userId + ex.getMessage());
            return ret;
        }

    }

    /**
     * 返回当前所有在线的用户
     *
     * @return
     */
    public static List<String> list() {
        List<String> users = new ArrayList<>();
        ConcurrentHashMap<String, FileStoreWebSocketServer> userMap = FileStoreWebSocketServer.getWebSocketMap();
        if (userMap == null || userMap.isEmpty()) {
            return users;
        }
        userMap.forEach((k, v) -> {
            users.add(k);
        });
        return users;
    }

    public static Map sendOrderStatus(OrderStatusMsgVo orderStatusMsgVo) throws Exception {
        ConcurrentHashMap<String, FileStoreWebSocketServer> userMap = FileStoreWebSocketServer.getWebSocketMap();
        ConcurrentHashSet<String> wsSet4App = FileStoreWebSocketServer.getWsSet4App();
        Enumeration<String> enumeration = userMap.keys();
        int counts = 0;
        int sysAutoCheckCount = 0;//系统自动检测通知数量
        MessageVo<OrderStatusMsgVo> messageVo = new MessageVo<>();
        messageVo.setData(orderStatusMsgVo);
        String message = null;
        while (enumeration.hasMoreElements()) {
            String userId = enumeration.nextElement();
            FileStoreWebSocketServer webSocketServer = userMap.get(userId);
            log.info("uid:{},listerinModerId:{},changerModelId:{}", userId, webSocketServer.ListeningOrder, orderStatusMsgVo.getModelId());
            log.info("contains is true:{}", webSocketServer.ListeningOrder.contains(orderStatusMsgVo.getModelId()));
            if (contains(webSocketServer.ListeningOrder, orderStatusMsgVo.getModelId())) {
                //有监听这个modelId的websocket客户端
                messageVo.setType(MsgTypeEnum.listeningOrder);
                try {
                    message = JSONObject.toJSONString(messageVo);
                    webSocketServer.sendMessage(message);
                    log.info("通知成功：{}，msgBody:{}", webSocketServer.getUserId(), message);
                    if ("processed".equals(orderStatusMsgVo.getStatus())) {
                        webSocketServer.ListeningOrder.remove(orderStatusMsgVo.getModelId());
                    }
                    counts++;
                } catch (Exception ex) {
                    log.error("发送通知订单状态变更异常：userId:{},err:{}", webSocketServer.getUserId(), ExceptionUtils.getStackTrace(ex));
                }
            }
            if (("sysAutoCheck".equals(orderStatusMsgVo.getStatus()) && wsSet4App.contains(userId))) {
                messageVo.setType(MsgTypeEnum.listeningAutoCheck);
                message = JSONObject.toJSONString(messageVo);
                try {
                    webSocketServer.sendMessage(message);
                    log.info("前端模拟打开报价专用，通知成功：{}，msgBody:{}", webSocketServer.getUserId(), message);
                    counts++;
                    sysAutoCheckCount++;
                } catch (Exception ex) {
                    log.error("前端模拟打开报价专用，发送通知订单状态变更异常：userId:{},err:{}", webSocketServer.getUserId(), ExceptionUtils.getStackTrace(ex));
                }
            }
        }
        Map<String, Integer> resultMap = new HashMap<>();
        resultMap.put("NormalClient", counts);
        resultMap.put("AutoCheckClient", sysAutoCheckCount);
        log.info("订单:{} 状态变更通知了：{} 个客户端", orderStatusMsgVo.getModelId(), counts);
        return resultMap;
    }

    private static boolean contains(Set<Long> modelIds, Long modelId) {
        if (modelIds == null || modelIds.isEmpty() || modelId == null) {
            log.info("modelIds 或 modelId为空");
            return false;
        }
        for (Object mid : modelIds) {
            if (String.valueOf(mid).equals(String.valueOf(modelId))) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Set<Long> ids = new HashSet<>();
        ids.add(123l);
        ids.add(23l);
        System.out.println(ids.contains(123l));
    }
}
